
package com.huaweicloud.saaslanding.install.applicationservice.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.huaweicloud.saaslanding.basic.enumeration.ComponentLabelEnum;
import com.huaweicloud.saaslanding.basic.enumeration.ServiceManageFrameTypeEnum;
import com.huaweicloud.saaslanding.basic.exception.BizException;
import com.huaweicloud.saaslanding.basic.exception.code.ExceptionCode;
import com.huaweicloud.saaslanding.basic.utils.CheckNullUtil;
import com.huaweicloud.saaslanding.dao.common.entity.deployedresource.CseResource;
import com.huaweicloud.saaslanding.dao.common.repository.deployedresource.CseResourceBaseMapper;
import com.huaweicloud.saaslanding.huawei.cse.api.CseConfigApi;
import com.huaweicloud.saaslanding.huawei.cse.request.CseConfigCreateRequest;
import com.huaweicloud.saaslanding.huawei.cse.response.CseConfigResponse;
import com.huaweicloud.saaslanding.huawei.cse.util.CseHeaderUtil;
import com.huaweicloud.saaslanding.install.applicationservice.CseResourceService;
import com.huaweicloud.saaslanding.install.dto.ServiceManageFrameworkDto;
import com.huaweicloud.saaslanding.install.json.ServiceManageFrameworkRequestBody;
import com.huaweicloud.saaslanding.install.properties.Cse;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;

/**
 * 功能描述
 *
 * @since 2022-07-29
 */
@Slf4j
public class CseServiceImpl extends AbstractServiceManageFrameServiceImpl {
    @Resource
    private ServiceManageFrameworkRequestBody serviceManageFrameworkRequestBody;

    @Resource
    private CseResourceBaseMapper cseResourceBaseMapper;

    @Resource
    private CseResourceService cseResourceService;

    @Resource
    private Cse cse;

    @Override
    public void createServiceManageFrameConfig(ServiceManageFrameworkDto serviceManageFrameworkDto) {
        log.info("========== start: 创建 cse 基础配置项 : {} ==========", serviceManageFrameworkDto.getServiceName());

        CseConfigCreateRequest configCreateRequest =
            serviceManageFrameworkRequestBody.createBasicConfigJson(serviceManageFrameworkDto);
        Map<String, String> headers =
            CseHeaderUtil.getHeaders(cse.getDiscoveryAddress(), cse.getName(), cse.getPassword());
        CseConfigResponse configResponse =
            CseConfigApi.create(cse.getConfigAddress(), cse.getCseProjectId(), headers, configCreateRequest);

        String kvIdBasic;
        try {
            String dynamicRouteConfigId = createDynamicRouteConfig(serviceManageFrameworkDto);
            String dynamicRouteLinkId = createDynamicRouteLinkConfig(serviceManageFrameworkDto);
            kvIdBasic = configResponse.getId();
            log.info("========== end: 创建 cse 基础配置项 : {} ==========", serviceManageFrameworkDto.getServiceName());

            // 创建灰度升级配置文件
            createUpgradeConfig(serviceManageFrameworkDto, kvIdBasic, dynamicRouteConfigId, dynamicRouteLinkId);
        } catch (Exception e) {
            log.error("!!!!!!!!!! 创建 cse 基础配置项 {} 失败 !!!!!!!!!!", serviceManageFrameworkDto.getServiceName());
            throw BizException.wrap(ExceptionCode.CSE_CONFIG_PARTIAL_SUCCESS, e);
        }
    }

    /**
     * 网关路由配置
     */
    private String createDynamicRouteConfig(ServiceManageFrameworkDto serviceManageFrameworkDto) {
        String label = serviceManageFrameworkDto.getLabel();
        String dynamicRouteId = StrUtil.EMPTY;

        if (ComponentLabelEnum.GATEWAY.getLabel().equals(label)) {
            log.info("创建 cse 网关动态路由配置项...");

            // 创建dynamic-route配置
            CseConfigCreateRequest dynamicRouteRequestBody =
                serviceManageFrameworkRequestBody.initCseDynamicRoute(serviceManageFrameworkDto);
            Map<String, String> headers =
                CseHeaderUtil.getHeaders(cse.getDiscoveryAddress(), cse.getName(), cse.getPassword());
            CseConfigResponse configResponse =
                CseConfigApi.create(cse.getConfigAddress(), cse.getCseProjectId(), headers, dynamicRouteRequestBody);
            dynamicRouteId = configResponse.getId();
        }
        return dynamicRouteId;
    }

    /**
     * 全链路灰度路由配置
     *
     * @param serviceManageFrameworkDto
     * @return
     */
    private String createDynamicRouteLinkConfig(ServiceManageFrameworkDto serviceManageFrameworkDto) {
        String label = serviceManageFrameworkDto.getLabel();
        String dynamicRouteLinkId = StrUtil.EMPTY;

        if (ComponentLabelEnum.GATEWAY.getLabel().equals(label)) {
            log.info("创建 cse 网关全链路灰度路由配置项...");

            // 创建dynamic-route-link配置
            CseConfigCreateRequest dynamicRouteRequestBody =
                serviceManageFrameworkRequestBody.initCseDynamicRouteLink(serviceManageFrameworkDto);
            Map<String, String> headers =
                CseHeaderUtil.getHeaders(cse.getDiscoveryAddress(), cse.getName(), cse.getPassword());
            CseConfigResponse configResponse =
                CseConfigApi.create(cse.getConfigAddress(), cse.getCseProjectId(), headers, dynamicRouteRequestBody);
            dynamicRouteLinkId = configResponse.getId();
        }
        return dynamicRouteLinkId;
    }

    /**
     * 创建微服务升级配置项
     */
    private void createUpgradeConfig(ServiceManageFrameworkDto serviceManageFrameworkDto, String kvIdBasic,
        String dynamicRouteConfigId, String dynamicRouteLinkId) {
        log.info("========== start: 创建 cse 升级配置项 : {} ==========", serviceManageFrameworkDto.getServiceName());

        CseConfigCreateRequest configCreateRequest =
            serviceManageFrameworkRequestBody.createCseUpgradeConfigJson(serviceManageFrameworkDto);
        Map<String, String> headers =
            CseHeaderUtil.getHeaders(cse.getDiscoveryAddress(), cse.getName(), cse.getPassword());
        CseConfigResponse configResponse =
            CseConfigApi.create(cse.getConfigAddress(), cse.getCseProjectId(), headers, configCreateRequest);

        String grayRouteKvId = configResponse.getId();
        try {
            log.info("========== end: 创建 cse 升级配置项 : {} ==========", serviceManageFrameworkDto.getServiceName());

            // 保存配置
            cseResourceService.saveCseResource(serviceManageFrameworkDto, kvIdBasic, grayRouteKvId,
                dynamicRouteConfigId, dynamicRouteLinkId, ServiceManageFrameTypeEnum.CSE.getName());
        } catch (Exception e) {
            log.error("!!!!!!!!!! 创建 cse 升级配置项 {} 失败 !!!!!!!!!!", serviceManageFrameworkDto.getServiceName());
            throw BizException.wrap(ExceptionCode.CSE_CONFIG_PARTIAL_SUCCESS, e);
        }
    }

    @Override
    public void deleteAllConfig() {
        log.info("========== start: 删除 所有 CSE 配置文件 ==========");

        // 获取所有数据库中保存的配置项id
        QueryWrapper<CseResource> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CseResource::getIsDel, 0);
        List<CseResource> cseResourceList = cseResourceBaseMapper.selectList(queryWrapper);

        if (CollectionUtil.isEmpty(cseResourceList)) {
            log.info("========== end: 删除 所有 CSE 配置文件 ==========");
            return;
        }

        for (CseResource cseResource : cseResourceList) {
            String id = cseResource.getId().toString();
            String basicKvId = CheckNullUtil.isNull(cseResource.getBasicKvId()) ? "" : (cseResource.getBasicKvId());
            String upgradeKvId =
                CheckNullUtil.isNull(cseResource.getGrayRouteKvId()) ? "" : cseResource.getGrayRouteKvId();
            String dynamicRouteKvId =
                CheckNullUtil.isNull(cseResource.getDynamicRouteKvId()) ? "" : cseResource.getDynamicRouteKvId();

            String dynamicRouteLinkKvId = CheckNullUtil.isNull(cseResource.getDynamicRouteLinkKvId()) ? ""
                : cseResource.getDynamicRouteLinkKvId();

            int deleteCount = 0;

            // 删除基础配置型
            if (deleteOneCseConfig(basicKvId)) {
                deleteCount++;
            }

            // 删除升级配置项
            if (deleteOneCseConfig(upgradeKvId)) {
                deleteCount++;
            }

            // 删除路由配置项
            if (deleteOneCseConfig(dynamicRouteKvId)) {
                deleteCount++;
            }

            // 删除全链路路由配置项
            if (deleteOneCseConfig(dynamicRouteLinkKvId)) {
                deleteCount++;
            }

            if (deleteCount == 4) {
                UpdateWrapper<CseResource> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("is_del", 1).eq("id", id);
                cseResourceBaseMapper.update(null, updateWrapper);
            }
        }

        deleteAllConfig();
    }

    /**
     * 删除一个cse配置文件
     */
    private Boolean deleteOneCseConfig(String kvId) {
        if (StringUtils.isBlank(kvId)) {
            return true;
        }

        Map<String, String> headers =
            CseHeaderUtil.getHeaders(cse.getDiscoveryAddress(), cse.getName(), cse.getPassword());
        boolean deleted;
        try {
            deleted = CseConfigApi.delete(cse.getConfigAddress(), cse.getCseProjectId(), kvId, headers);
        } catch (BizException e) {
            if (e.getCause().getMessage().contains("Not Found")) {
                log.info("配置项 {} 不存在!", kvId);
                deleted = true;
            } else {
                log.error("删除配置项 {} 失败!", kvId);
                throw BizException.wrap(ExceptionCode.CONFIG_DELETE_FAILED, e);
            }
        }

        log.info("删除配置项 {} 成功!", kvId);
        return deleted;
    }

}
